/**
 * @file bsp_uart_v2.c
 * @brief 新版UART封装驱动
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 2.0
 * @date 2020-10-10
 * @copyright Copyright (c) 2020  烽火通信
 ***************************************************************
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version  <th>Author  <th>Description
 * <tr><td>2020-10-10 <td>1.0      <td>wangh   <td>内容
 * </table>
 */
#include "bsp_uart_v2.h"
#include <bsp.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

#undef LOG_LEVEL_
#define LOG_LEVEL_ 	LOG_LVL_ASSERT
#include "bsp_log.h"

#ifdef STM32F10X
#if (LOG_UART == 1)
#define DEBUG_USARTx    USART1
#elif (LOG_UART == 2)
#define DEBUG_USARTx    USART2
#elif (LOG_UART == 3)
#define DEBUG_USARTx    USART3
#elif (LOG_UART == 4)
#define DEBUG_USARTx    UART4
#elif (LOG_UART == 5)
#define DEBUG_USARTx    UART5
#endif

#elif defined GD32F10X
#if (LOG_UART == 1)
#define DEBUG_USARTx    USART0
#elif (LOG_UART == 2)
#define DEBUG_USARTx    USART1
#elif (LOG_UART == 3)
#define DEBUG_USARTx    USART2
#elif (LOG_UART == 4)
#define DEBUG_USARTx    UART3
#elif (LOG_UART == 5)
#define DEBUG_USARTx    UART4
#endif
#endif


static Uart_t UartObj[5];

static void UartDmaConfig( UartId_t uartId, uint8_t *buff, uint32_t size );


/**
 * @brief UART初始化
 * @warning 串口引脚要与外设编号严格对应，驱动未作匹配校验
 * @param[in]  uartId   UART编号
 * @param[in]  tx       TX引脚
 * @param[in]  rx       RX引脚
 * @param[in]  maxRxSize 接收最大帧长(This size must be a power of two)
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_ALREADY_INIT - 已初始化
 * - @ref BSP_ERROR_NO_MEM - 内存出错
 */
int8_t UartInit( UartId_t uartId, PinNames tx, PinNames rx, uint16_t maxRxSize )
{
    if( uartId > UART_5 )
    {
        log_e( "UartInit error: no this uartId(%d)\r\n", uartId );
        return BSP_ERROR_INVALID_PARAM;
    }
    if( UartObj[uartId].IsInitialized == true )
    {
        log_w( "UART%d has already Initialized, please use UartDeInit first\r\n", uartId+1 );
        return BSP_ERROR_ALREADY_INIT;
    }

    UartObj[uartId].UartId = uartId;

    if( maxRxSize > 2048 )
        maxRxSize = 2048;
    
    UartObj[uartId].FifoRx_size = maxRxSize * 2;
    UartObj[uartId].FifoRx_buf = pvPortMalloc(maxRxSize * 2);
    if( FIFO_SUCCESS != app_fifo_init(&UartObj[uartId].FifoRx, UartObj[uartId].FifoRx_buf, UartObj[uartId].FifoRx_size) )
    {
        log_e("UART%d FifoRx init error\r\n", uartId+1);
        return BSP_ERROR_NO_MEM;
    }

    if (uartId < UART_5)
    {
        UartObj[uartId].dmaRx_buf = pvPortMalloc(maxRxSize);
        UartObj[uartId].dmaRx_size = maxRxSize;
    }

    UartObj[uartId].uartRxSemaphore = xSemaphoreCreateBinary(); /* 初始时信号值为0 */
    if(UartObj[uartId].uartRxSemaphore == NULL)
    {
        log_e("UART%d uartRxSemaphore create error\r\n", uartId+1);
        return BSP_ERROR_NO_MEM;
    }

    UartObj[uartId].uartTxLock = xSemaphoreCreateBinary();  /* 初始时信号值为0 */
    if(UartObj[uartId].uartTxLock == NULL)
    {
        log_e("UART%d uartTxLock create error\r\n", uartId+1);
        return BSP_ERROR_NO_MEM;
    }
    xSemaphoreGive( UartObj[uartId].uartTxLock );


    ENTER_CRITICAL( );

#ifdef STM32F10X
    GpioInit( &UartObj[uartId].Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_NO_PULL, 2 ); /* 复用推挽输出 */
    GpioInit( &UartObj[uartId].Rx, rx, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 2 );         /* 上拉输入 */

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=4; /* 抢占优先级3 */
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;       /* 子优先级3 */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         /* IRQ通道使能 */

    switch (uartId)
    {
    case UART_1:
        UartObj[uartId].USARTx = USART1;
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE );
        UartObj[uartId].UART_RX_DMA_Channel = DMA1_Channel5;
        UartObj[uartId].UART_DMA_FLAG = DMA1_FLAG_GL5;
        UartObj[uartId].DMA_PeripheralAddr = 0x40013804;
        RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       //串口1中断通道
        NVIC_Init(&NVIC_InitStructure);	                        //根据指定的参数初始化VIC寄存器
        break;

    case UART_2:
        UartObj[uartId].USARTx = USART2;
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );
        UartObj[uartId].UART_RX_DMA_Channel = DMA1_Channel6;
        UartObj[uartId].UART_DMA_FLAG = DMA1_FLAG_GL6;
        UartObj[uartId].DMA_PeripheralAddr = 0x40004404;
        RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;       //串口1中断通道
        NVIC_Init(&NVIC_InitStructure);	                        //根据指定的参数初始化VIC寄存器
        break;

    case UART_3:
        UartObj[uartId].USARTx = USART3;
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE );
        UartObj[uartId].UART_RX_DMA_Channel = DMA1_Channel3;
        UartObj[uartId].UART_DMA_FLAG = DMA1_FLAG_GL3;
        UartObj[uartId].DMA_PeripheralAddr = 0x40004804;
        RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;       //串口1中断通道
        NVIC_Init(&NVIC_InitStructure);	                        //根据指定的参数初始化VIC寄存器
        break;

    case UART_4:
        UartObj[uartId].USARTx = UART4;
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_UART4, ENABLE );
        UartObj[uartId].UART_RX_DMA_Channel = DMA2_Channel3;
        UartObj[uartId].UART_DMA_FLAG = DMA2_FLAG_GL3;
        UartObj[uartId].DMA_PeripheralAddr = 0x40004C04;
        RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA2, ENABLE );
        NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;       //串口1中断通道
        NVIC_Init(&NVIC_InitStructure);	                        //根据指定的参数初始化VIC寄存器
        break;

    case UART_5:
        UartObj[uartId].USARTx = UART5;
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_UART5, ENABLE );
        NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;       //串口1中断通道
        NVIC_Init(&NVIC_InitStructure);	                        //根据指定的参数初始化VIC寄存器
        break;

    default:
        break;
    }

#elif defined GD32F10X

    GpioInit( &UartObj[uartId].Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_NO_PULL, 2 ); /* 复用推挽输出 */
    GpioInit( &UartObj[uartId].Rx, rx, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 2 );         /* 上拉输入 */

    switch (uartId)
    {
    case UART_1:
    {
        UartObj[uartId].USARTx = USART0;
        rcu_periph_clock_enable( RCU_USART0 );
        usart_deinit( USART0 );

        rcu_periph_clock_enable( RCU_DMA0 );
        UartObj[uartId].dma_periph = DMA0;
        UartObj[uartId].dma_channel = DMA_CH4;
        UartObj[uartId].UART_DMA_FLAG = DMA_FLAG_G;
        UartObj[uartId].DMA_PeripheralAddr = ((uint32_t)&USART_DATA(USART0));
        
        nvic_irq_enable(USART0_IRQn, 4, 0);
    } break;
    
    case UART_2:
    {
        UartObj[uartId].USARTx = USART1;
        rcu_periph_clock_enable( RCU_USART1 );
        usart_deinit( USART1 );

        rcu_periph_clock_enable( RCU_DMA0 );
        UartObj[uartId].dma_periph = DMA0;
        UartObj[uartId].dma_channel = DMA_CH5;
        UartObj[uartId].UART_DMA_FLAG = DMA_FLAG_G;
        UartObj[uartId].DMA_PeripheralAddr = ((uint32_t)&USART_DATA(USART1));
        
        nvic_irq_enable(USART1_IRQn, 4, 0);
    } break;

    case UART_3:
    {
        UartObj[uartId].USARTx = USART2;
        rcu_periph_clock_enable( RCU_USART2 );
        usart_deinit( USART2 );
        
        rcu_periph_clock_enable( RCU_DMA0 );
        UartObj[uartId].dma_periph = DMA0;
        UartObj[uartId].dma_channel = DMA_CH2;
        UartObj[uartId].UART_DMA_FLAG = DMA_FLAG_G;
        UartObj[uartId].DMA_PeripheralAddr = ((uint32_t)&USART_DATA(USART2));
        
        nvic_irq_enable(USART2_IRQn, 4, 0);
    } break;

#ifndef GD32F10X_MD
    case UART_4:
    {
        UartObj[uartId].USARTx = UART3;
        rcu_periph_clock_enable( RCU_UART3 );
        usart_deinit( UART3 );
        
        rcu_periph_clock_enable( RCU_DMA1 );
        UartObj[uartId].dma_periph = DMA1;
        UartObj[uartId].dma_channel = DMA_CH2;
        UartObj[uartId].UART_DMA_FLAG = DMA_FLAG_G;
        UartObj[uartId].DMA_PeripheralAddr = ((uint32_t)&USART_DATA(UART3));
        
        nvic_irq_enable(UART3_IRQn, 4, 0);
    } break;

    case UART_5:
    {
        UartObj[uartId].USARTx = UART4;
        rcu_periph_clock_enable( RCU_UART4 );
        
        nvic_irq_enable(UART4_IRQn, 4, 0);
    } break;
#endif

    default:
        break;
    }

#endif

    UartReset( uartId );

    EXIT_CRITICAL( );

    UartObj[uartId].IsInitialized = true;

    return BSP_SUCCESS;
}

/**
 * @brief UART去初始化
 * @param  uartId      UART编号
 */
void UartDeInit( UartId_t uartId )
{
    if( uartId > UART_5 )
        return;

    UartObj[uartId].IsInitialized = false;
#ifdef STM32F10X
    USART_Cmd( UartObj[uartId].USARTx, DISABLE );
    USART_DeInit( UartObj[uartId].USARTx );
#elif defined GD32F10X
    usart_disable( UartObj[uartId].USARTx );
    usart_deinit( UartObj[uartId].USARTx );
#endif

    GpioInit( &UartObj[uartId].Tx, UartObj[uartId].Tx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
    GpioInit( &UartObj[uartId].Rx, UartObj[uartId].Rx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );

    if( uartId < UART_5 )
    {
        if (UartObj[uartId].dmaRx_buf)
            vPortFree(UartObj[uartId].dmaRx_buf);
        if (UartObj[uartId].FifoRx_buf)
            vPortFree(UartObj[uartId].FifoRx_buf);
        if (UartObj[uartId].uartRxSemaphore)
            vSemaphoreDelete( UartObj[uartId].uartRxSemaphore );
        if (UartObj[uartId].uartTxLock)
            vSemaphoreDelete( UartObj[uartId].uartTxLock );
    }
}

/**
 * @brief UART硬件外设初始化（可用于重新初始化或复位UART）
 * @param[in]  uartId   UART编号
 */
void UartReset( UartId_t uartId )
{
    /* 串口复位 */
#ifdef STM32F10X
    USART_DeInit( UartObj[uartId].USARTx );
#elif defined GD32F10X
    usart_deinit( UartObj[uartId].USARTx );
#endif

    /* 串口参数配置 */
    if (UartObj[uartId].IsInitialized == false)
    {
        UartConfig( uartId, RX_TX, 9600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
    }
    else
    {
        UartConfig( uartId, UartObj[uartId].param.mode, UartObj[uartId].param.baudrate, UartObj[uartId].param.wordLength, 
                            UartObj[uartId].param.stopBits, UartObj[uartId].param.parity, UartObj[uartId].param.flowCtrl );
    }

#ifdef STM32F10X

    USART_Cmd(UartObj[uartId].USARTx, DISABLE);
    USART_ITConfig(UartObj[uartId].USARTx, USART_IT_ERR, ENABLE);   /* 开启串口错误中断（FE、NE、ORE） */
    USART_ITConfig(UartObj[uartId].USARTx, USART_IT_PE, ENABLE);    /* 开启串口校验错误中断 */
    USART_ITConfig(UartObj[uartId].USARTx, USART_IT_IDLE, ENABLE);  /* 开启串口空闲IDEL中断 */
    if( uartId == UART_5 )  /* 串口5不支持DMA */
    {
        USART_ITConfig(UartObj[uartId].USARTx, USART_IT_RXNE, ENABLE);  /* 开启串口接收中断 */
#if UART5_IDLE_DISABLE
        USART_ITConfig(UartObj[uartId].USARTx, USART_IT_IDLE, DISABLE);
#endif
    }
    else
    {
        USART_DMACmd(UartObj[uartId].USARTx, USART_DMAReq_Rx, ENABLE);  /* 开启串口DMA接收 */
    }

    USART_ClearFlag(UartObj[uartId].USARTx, USART_FLAG_TC);             /* 清标志位 */
    USART_Cmd(UartObj[uartId].USARTx, ENABLE);

#elif defined GD32F10X

    usart_disable( UartObj[uartId].USARTx );
    usart_interrupt_enable( UartObj[uartId].USARTx, USART_INT_ERR );    /* 开启串口错误中断（FE、NE、ORE） */
    usart_interrupt_enable( UartObj[uartId].USARTx, USART_INT_PERR );   /* 开启串口校验错误中断 */
    usart_interrupt_enable( UartObj[uartId].USARTx, USART_INT_IDLE );   /* 开启串口空闲IDEL中断 */
    if( uartId == UART_5 )  /* 串口5不支持DMA */
    {
        usart_interrupt_enable( UartObj[uartId].USARTx, USART_INT_RBNE );   /* 开启串口接收中断 */
#if UART5_IDLE_DISABLE
        usart_interrupt_disable( UartObj[uartId].USARTx, USART_INT_IDLE );
#endif
    }
    else
    {
        usart_dma_receive_config( UartObj[uartId].USARTx, USART_DENR_ENABLE );  /* 开启串口DMA接收 */
    }
    
    usart_flag_clear( UartObj[uartId].USARTx, USART_FLAG_TC );	/* 清标志位 */
    usart_enable( UartObj[uartId].USARTx );
#endif

    if( uartId < UART_5 )
        UartDmaConfig( uartId, UartObj[uartId].dmaRx_buf, UartObj[uartId].dmaRx_size ); /* 首次接收DMA配置 */
}

/**
 * @brief UART参数配置
 * @param  uartId      UART编号
 * @param  mode        UART工作模式
 * @param  baudrate    波特率
 * @param  wordLength  传输字长度
 * @param  stopBits    停止位
 * @param  parity      校验位
 * @param  flowCtrl    流控
 * @return int8_t BSP_SUCCESS:成功
 */
int8_t UartConfig( UartId_t uartId, UartMode_t mode, uint32_t baudrate, WordLength_t wordLength, StopBits_t stopBits, Parity_t parity, FlowCtrl_t flowCtrl )
{
    if( uartId > UART_5 )
    {
        log_e( "UartInit error: no this uartId(%d)\r\n", uartId );
        return BSP_ERROR_INVALID_PARAM;
    }

    if( UartObj[uartId].IsInitialized == false )
    {
        log_e( "UART%d no Initialized, please use UartInit first\r\n", uartId+1 );
        return BSP_ERROR_NO_INIT;
    }

#ifdef STM32F10X
    USART_InitTypeDef USART_InitStructure;
    USART_StructInit( &USART_InitStructure );  /* UART结构体默认初始化（9600,8,1,none） */
    USART_Cmd( UartObj[uartId].USARTx, DISABLE );

    if( baudrate > 0 )
        USART_InitStructure.USART_BaudRate = baudrate;

    if( mode == TX_ONLY )
    {
        USART_InitStructure.USART_Mode = USART_Mode_Tx;
    }
    else if( mode == RX_ONLY )
    {
        USART_InitStructure.USART_Mode = USART_Mode_Rx;
    }
    else if( mode == RX_TX )
    {
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    }

    if( wordLength == UART_8_BIT )
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    else if( wordLength == UART_9_BIT )
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;

    if ( stopBits == UART_1_STOP_BIT )
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
    else if ( stopBits == UART_0_5_STOP_BIT )
        USART_InitStructure.USART_StopBits = USART_StopBits_0_5;
    else if ( stopBits == UART_2_STOP_BIT )
        USART_InitStructure.USART_StopBits = USART_StopBits_2;
    else if ( stopBits == UART_1_5_STOP_BIT )
        USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
    
    if( parity == NO_PARITY )
        USART_InitStructure.USART_Parity = USART_Parity_No;
    else if( parity == EVEN_PARITY )
        USART_InitStructure.USART_Parity = USART_Parity_No;
    else if( parity == ODD_PARITY )
        USART_InitStructure.USART_Parity = USART_Parity_No;

    if( flowCtrl == NO_FLOW_CTRL )
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    else if( flowCtrl == RTS_FLOW_CTRL )
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS;
    else if( flowCtrl == CTS_FLOW_CTRL )
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_CTS;
    else if( flowCtrl == RTS_CTS_FLOW_CTRL )
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;

    USART_Init( UartObj[uartId].USARTx, &USART_InitStructure );
    USART_Cmd( UartObj[uartId].USARTx, ENABLE );

#elif defined GD32F10X
    usart_disable( UartObj[uartId].USARTx );

    if( baudrate > 0 )
        usart_baudrate_set( UartObj[uartId].USARTx, baudrate );

    if( mode == TX_ONLY )
    {
        usart_transmit_config( UartObj[uartId].USARTx, USART_TRANSMIT_ENABLE );
        usart_receive_config( UartObj[uartId].USARTx, USART_RECEIVE_DISABLE );
    }
    else if( mode == RX_ONLY )
    {
        usart_transmit_config( UartObj[uartId].USARTx, USART_TRANSMIT_DISABLE );
        usart_receive_config( UartObj[uartId].USARTx, USART_RECEIVE_ENABLE );
    }
    else if( mode == RX_TX )
    {
        usart_transmit_config( UartObj[uartId].USARTx, USART_TRANSMIT_ENABLE );
        usart_receive_config( UartObj[uartId].USARTx, USART_RECEIVE_ENABLE );
    }

    if( wordLength == UART_8_BIT )
        usart_word_length_set( UartObj[uartId].USARTx, USART_WL_8BIT );
    else if( wordLength == UART_9_BIT )
        usart_word_length_set( UartObj[uartId].USARTx, USART_WL_9BIT );

    if ( stopBits == UART_1_STOP_BIT )
        usart_stop_bit_set( UartObj[uartId].USARTx, USART_STB_1BIT );
    else if ( stopBits == UART_0_5_STOP_BIT )
        usart_stop_bit_set( UartObj[uartId].USARTx, USART_STB_0_5BIT );
    else if ( stopBits == UART_2_STOP_BIT )
        usart_stop_bit_set( UartObj[uartId].USARTx, USART_STB_2BIT );
    else if ( stopBits == UART_1_5_STOP_BIT )
        usart_stop_bit_set( UartObj[uartId].USARTx, USART_STB_1_5BIT );
    
    if( parity == NO_PARITY )
        usart_parity_config( UartObj[uartId].USARTx, USART_PM_NONE );
    else if( parity == EVEN_PARITY )
        usart_parity_config( UartObj[uartId].USARTx, USART_PM_EVEN );
    else if( parity == ODD_PARITY )
        usart_parity_config( UartObj[uartId].USARTx, USART_PM_ODD );

    if( flowCtrl == NO_FLOW_CTRL )
    {
        usart_hardware_flow_rts_config( UartObj[uartId].USARTx, USART_RTS_DISABLE );
        usart_hardware_flow_cts_config( UartObj[uartId].USARTx, USART_CTS_DISABLE );
    }
    else if( flowCtrl == RTS_FLOW_CTRL )
    {
        usart_hardware_flow_rts_config( UartObj[uartId].USARTx, USART_RTS_ENABLE );
        usart_hardware_flow_cts_config( UartObj[uartId].USARTx, USART_CTS_DISABLE );
    }
    else if( flowCtrl == CTS_FLOW_CTRL )
    {
        usart_hardware_flow_rts_config( UartObj[uartId].USARTx, USART_RTS_DISABLE );
        usart_hardware_flow_cts_config( UartObj[uartId].USARTx, USART_CTS_ENABLE );
    }
    else if( flowCtrl == RTS_CTS_FLOW_CTRL )
    {
        usart_hardware_flow_rts_config( UartObj[uartId].USARTx, USART_RTS_ENABLE );
        usart_hardware_flow_cts_config( UartObj[uartId].USARTx, USART_CTS_ENABLE );
    }

    usart_enable( UartObj[uartId].USARTx );
#endif

    return BSP_SUCCESS;
}

/**
 * @brief UART接收DMA配置
 * @param  uartId      UART编号
 * @param  buff        DMA发送/接收缓存
 * @param  size        DMA发送/接收长度
 */
static void UartDmaConfig( UartId_t uartId, uint8_t *buff, uint32_t size )
{
#ifdef STM32F10X
    DMA_InitTypeDef DMA_InitStructure;

    DMA_DeInit( UartObj[uartId].UART_RX_DMA_Channel );                          /* 恢复缺省值 */
    DMA_InitStructure.DMA_PeripheralBaseAddr = UartObj[uartId].DMA_PeripheralAddr;  /* 设置串口接收数据寄存器 */
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buff;                      /* 设置接收缓冲区首地址 */
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                          /* 设置外设为数据源，外设寄存器 -> 内存缓冲区 */
    DMA_InitStructure.DMA_BufferSize = size;                                    /* 需要最大可能接收到的字节数 */
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            /* 外设地址不做增加调整，调整不调整是DMA自动实现的 */
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     /* 内存缓冲区地址增加调整 */
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;     /* 外设数据宽度8位，1个字节 */
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;             /* 内存数据宽度8位，1个字节 */
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                               /* 单次传输模式 */
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                     /* 优先级设置 */
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                /* 关闭内存到内存的DMA模式 */
    DMA_Init(UartObj[uartId].UART_RX_DMA_Channel, &DMA_InitStructure);          /* 写入配置 */
    DMA_ClearFlag(UartObj[uartId].UART_DMA_FLAG);                               /* 清除DMA所有标志 */
    DMA_Cmd(UartObj[uartId].UART_RX_DMA_Channel, ENABLE);

#elif defined GD32F10X
    dma_parameter_struct dma_init_struct;

    dma_deinit( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel );
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.periph_addr = UartObj[uartId].DMA_PeripheralAddr;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_addr = (uint32_t)buff;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.number = size;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel, &dma_init_struct );

    dma_circulation_disable( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel );
    dma_memory_to_memory_disable( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel );

    dma_flag_clear( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel, UartObj[uartId].UART_DMA_FLAG );
    dma_channel_enable( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel );
#endif
}

/**
 * @brief UART中断DMA接收处理函数
 * @param  uartId      UART编号
 */
static void UartIrqHandler( UartId_t uartId )
{
    // log_d( "UART%d UartIrqHandler\r\n", uartId+1 );
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

#ifdef STM32F10X
    if(USART_GetITStatus(UartObj[uartId].USARTx, USART_IT_IDLE) != RESET)   /* 空闲中断 */
    {
        DMA_Cmd(UartObj[uartId].UART_RX_DMA_Channel, DISABLE);      /* 关闭DMA ，防止干扰 */
        DMA_ClearFlag(UartObj[uartId].UART_DMA_FLAG);               /* 清DMA标志位 */
        
        uint32_t rev_data_len = UartObj[uartId].dmaRx_size - DMA_GetCurrDataCounter(UartObj[uartId].UART_RX_DMA_Channel);
        if(rev_data_len > 0)    /* 接收数据长度 */
        {
            app_fifo_write(&UartObj[uartId].FifoRx, UartObj[uartId].dmaRx_buf, (uint32_t *)&rev_data_len);
            memset(UartObj[uartId].dmaRx_buf, 0, UartObj[uartId].dmaRx_size);
        }

        if( pdPASS == xSemaphoreGiveFromISR( UartObj[uartId].uartRxSemaphore, &xHigherPriorityTaskWoken ) )
        {
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
        }

        UartDmaConfig( uartId, UartObj[uartId].dmaRx_buf, UartObj[uartId].dmaRx_size );
        
        USART_ReceiveData(UartObj[uartId].USARTx);  /* Clear IDLE interrupt flag bit */
    }

    /* 过载错误 帧错误 噪声错误 校验错误 */
    if ((USART_GetITStatus(UartObj[uartId].USARTx, USART_IT_ORE) != RESET) || \
        (USART_GetITStatus(UartObj[uartId].USARTx, USART_IT_FE) != RESET) || \
        (USART_GetITStatus(UartObj[uartId].USARTx, USART_IT_NE) != RESET) || \
        (USART_GetITStatus(UartObj[uartId].USARTx, USART_IT_PE) != RESET) )
    {
        USART_ReceiveData(UartObj[uartId].USARTx);  /* Clear interrupt flag bit */
        // UartReset( uartId );    /* 复位串口 */
        log_e( "UART%d communication error!\r\n", uartId+1 );
    }

#elif defined GD32F10X
    if ( usart_interrupt_flag_get( UartObj[uartId].USARTx, USART_INT_FLAG_IDLE ) != RESET )   /* 空闲中断 */
    {
        dma_channel_disable( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel );	/* 关闭DMA ，防止干扰 */
        dma_flag_clear( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel, UartObj[uartId].UART_DMA_FLAG );	/* 清DMA标志位 */
        
        uint32_t rev_data_len = UartObj[uartId].dmaRx_size - dma_transfer_number_get( UartObj[uartId].dma_periph, (dma_channel_enum)UartObj[uartId].dma_channel );
        if(rev_data_len > 0)    /* 接收数据长度 */
        {
            app_fifo_write(&UartObj[uartId].FifoRx, UartObj[uartId].dmaRx_buf, (uint32_t *)&rev_data_len);
            memset(UartObj[uartId].dmaRx_buf, 0, UartObj[uartId].dmaRx_size);
        }

        if( pdPASS == xSemaphoreGiveFromISR( UartObj[uartId].uartRxSemaphore, &xHigherPriorityTaskWoken ) )
        {
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
        }

        UartDmaConfig( uartId, UartObj[uartId].dmaRx_buf, UartObj[uartId].dmaRx_size );
        
        usart_data_receive( UartObj[uartId].USARTx );  /* Clear IDLE interrupt flag bit */
    }

    /* 过载错误 帧错误 噪声错误 校验错误 */
    if ((usart_interrupt_flag_get( UartObj[uartId].USARTx, USART_INT_FLAG_ERR_ORERR ) != RESET) || \
        (usart_interrupt_flag_get( UartObj[uartId].USARTx, USART_INT_FLAG_ERR_FERR ) != RESET) || \
        (usart_interrupt_flag_get( UartObj[uartId].USARTx, USART_INT_FLAG_ERR_NERR ) != RESET) || \
        (usart_interrupt_flag_get( UartObj[uartId].USARTx, USART_INT_FLAG_PERR ) != RESET))
    {
        usart_data_receive( UartObj[uartId].USARTx );  /* Clear interrupt flag bit */
        // UartReset( uartId );    /* 复位串口 */
        log_e( "UART%d communication error!\r\n", uartId+1 );
    }
#endif

    if( xHigherPriorityTaskWoken )
        taskYIELD();
}

#ifdef STM32F10X
void USART1_IRQHandler(void)
{
    UartIrqHandler( UART_1 );
}

void USART2_IRQHandler(void)
{
    UartIrqHandler( UART_2 );
}

void USART3_IRQHandler(void)
{
    UartIrqHandler( UART_3 );
}

void UART4_IRQHandler(void)
{
    UartIrqHandler( UART_4 );
}

void UART5_IRQHandler(void)
{
    if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)    /* 接收中断 */
    {
        USART_ClearITPendingBit(UART5, USART_IT_RXNE);      /* 清除中断标志 */
        
        app_fifo_put(&UartObj[UART_5].FifoRx, USART_ReceiveData(UART5));
    }

#if !UART5_IDLE_DISABLE
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	
    if(USART_GetITStatus(UART5, USART_IT_IDLE) != RESET)    /* 空闲中断 */
    {
        USART_ReceiveData(UART5);   /* 清IDLE中断 */
        
        if( pdPASS == xSemaphoreGiveFromISR( UartObj[UART_5].uartRxSemaphore, &xHigherPriorityTaskWoken ) )
        {
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
        }
    }
#endif

    /* 过载错误 帧错误 噪声错误 校验错误 */
    if ((USART_GetITStatus(UART5, USART_IT_ORE) != RESET) || \
        (USART_GetITStatus(UART5, USART_IT_FE) != RESET) || \
        (USART_GetITStatus(UART5, USART_IT_NE) != RESET) || \
        (USART_GetITStatus(UART5, USART_IT_PE) != RESET) )
    {
        USART_ReceiveData(UART5);  /* Clear interrupt flag bit */
        // UartReset( UART_5 ); /* 复位串口 */
        log_e( "UART5 communication error!\r\n" );
    }
}

#elif defined GD32F10X
void USART0_IRQHandler(void)
{
    UartIrqHandler( UART_1 );
}

void USART1_IRQHandler(void)
{
    UartIrqHandler( UART_2 );
}

void USART2_IRQHandler(void)
{
    UartIrqHandler( UART_3 );
}

#ifndef GD32F10X_MD
void UART3_IRQHandler(void)
{
    UartIrqHandler( UART_4 );
}

void UART4_IRQHandler(void)
{
    if ( usart_interrupt_flag_get( UART4, USART_INT_FLAG_RBNE ) != RESET )	/* 接收中断 */
    {
        usart_interrupt_flag_clear( UART4, USART_INT_FLAG_RBNE);	/* 清除中断标志 */
        
        app_fifo_put(&UartObj[UART_5].FifoRx, usart_data_receive(UART4));
    }

#if !UART5_IDLE_DISABLE
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if ( usart_interrupt_flag_get( UART4, USART_INT_FLAG_IDLE ) != RESET )   /* 空闲中断 */
    {
        usart_data_receive( UART4 );   /* 清IDLE中断 */
        
        if( pdPASS == xSemaphoreGiveFromISR( UartObj[UART_5].uartRxSemaphore, &xHigherPriorityTaskWoken ) )
        {
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
        }
    }
#endif

    /* 过载错误 帧错误 噪声错误 校验错误 */
    if ((usart_interrupt_flag_get( UART4, USART_INT_FLAG_ERR_ORERR ) != RESET) || \
        (usart_interrupt_flag_get( UART4, USART_INT_FLAG_ERR_FERR ) != RESET) || \
        (usart_interrupt_flag_get( UART4, USART_INT_FLAG_ERR_NERR ) != RESET) || \
        (usart_interrupt_flag_get( UART4, USART_INT_FLAG_PERR ) != RESET))
    {
        usart_data_receive( UART4 );  /* Clear interrupt flag bit */
        // UartReset( UART_5 ); /* 复位串口 */
        log_e( "UART5 communication error!\r\n" );
    }
}
#endif  /* GD32F10X_MD */
#endif  /* GD32F10X */

static uint32_t OsGetTickCount(void)
{
    register uint32_t __regIPSR     __ASM("ipsr");
    if (__regIPSR != 0)
        return xTaskGetTickCountFromISR();
    else
        return xTaskGetTickCount();
}

static int8_t UART_WaitOnFlagUntilTimeout( UartId_t uartId, uint32_t Flag, FlagStatus Status, uint32_t Timeout )
{
    uint32_t Tickstart = OsGetTickCount();

#ifdef STM32F10X
    while ((USART_GetFlagStatus(UartObj[uartId].USARTx, Flag) ? SET : RESET) == Status)
#elif defined GD32F10X
    while ((usart_flag_get(UartObj[uartId].USARTx, (usart_flag_enum)Flag) ? SET : RESET) == Status)
#endif
    {
        if (Timeout != portMAX_DELAY)
        {
            if (OsGetTickCount() < Tickstart)
                Tickstart = OsGetTickCount();

            if ((Timeout == 0U) || ((OsGetTickCount() - Tickstart) > Timeout))
            {
                /* 发送超时，复位串口 */
                // UartReset( uartId );
                return BSP_ERROR_TIMEOUT;
            }
        }
    }
    return BSP_SUCCESS;
}

/**
 * @brief UART发送
 * @param[in]  uartId       UART编号
 * @param[in]  buffer       发送数据指针
 * @param[in]  size         发送数据长度
 * @return int8_t 
 * - @b Success : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_NO_INIT - 串口没有初始化
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_TIMEOUT - 串口异常发送超时（内部自回复）
 */
int8_t UartSend( UartId_t uartId, uint8_t *buffer, uint16_t size )
{
    if ( UartObj[uartId].IsInitialized == false )
        return BSP_ERROR_NO_INIT;
    
    if ( (buffer == NULL) || (size == 0) )
        return BSP_ERROR_INVALID_PARAM;

#if UART_SEND_ENTER_CRITICAL    /* 串口发送进临界区执行，避免干扰 */
    taskENTER_CRITICAL();
#ifdef STM32F10X
    for( uint16_t i=0; i<size; i++ )
    {
        while(RESET == USART_GetFlagStatus(UartObj[uartId].USARTx, USART_FLAG_TXE));
        USART_SendData(UartObj[uartId].USARTx, buffer[i]);
    }
    while(RESET == USART_GetFlagStatus(UartObj[uartId].USARTx, USART_FLAG_TC));
#elif defined GD32F10X
    for( uint16_t i=0; i<size; i++ )
    {
        while(RESET == usart_flag_get(UartObj[uartId].USARTx, USART_FLAG_TBE));
        usart_data_transmit( UartObj[uartId].USARTx, buffer[i] );
    }
    while(RESET == usart_flag_get(UartObj[uartId].USARTx, USART_FLAG_TC));
#endif
    taskEXIT_CRITICAL();
#else

    xSemaphoreTake( UartObj[uartId].uartTxLock, portMAX_DELAY );
#ifdef STM32F10X
    USART_ClearFlag(UartObj[uartId].USARTx, USART_FLAG_TC);
#elif defined GD32F10X
    usart_flag_clear(UartObj[uartId].USARTx, USART_FLAG_TC);
#endif
    for( uint16_t i=0; i<size; i++ )
    {
#ifdef STM32F10X
        USART_SendData(UartObj[uartId].USARTx, buffer[i]);
#elif defined GD32F10X
        usart_data_transmit( UartObj[uartId].USARTx, buffer[i] );
#endif
        if (BSP_ERROR_TIMEOUT == UART_WaitOnFlagUntilTimeout( uartId, USART_FLAG_TC, RESET, 100 ))
        {
            xSemaphoreGive( UartObj[uartId].uartTxLock );
            return BSP_ERROR_TIMEOUT;
        }
    }
    xSemaphoreGive( UartObj[uartId].uartTxLock );
#endif

    return BSP_SUCCESS;
}

/**
 * @brief UART格式化输出
 * @bug 该接口仅支持100长度字符串
 * @param  uartId      UART编号
 * @param  fmt         格式化字符串
 */
void UartPrintf( UartId_t uartId, char *fmt, ... )
{
    if( UartObj[uartId].IsInitialized == false )
        return;

    char buffer[101];   /* NOTE:长度按实际需求更改 */

    va_list arg_ptr;
    va_start(arg_ptr, fmt);
    memset(buffer, 0, 101);
    vsnprintf(buffer, 100, fmt, arg_ptr);
    va_end(arg_ptr);
    UartSend(uartId, (uint8_t *)buffer, strlen(buffer));
}

/**
 * @brief UART接收
 * @param[in]  uartId       UART编号
 * @param[in]  buffer       接收缓存
 * @param[in]  size         接收长度（0：直接获取fifo长度）
 * @param[in]  blockTime    接收阻塞时间（0：直接轮询，portMAX_DELAY：不超时）
 * @return int32_t 
 * - @b Success : 实际FIFO长度 \n
 * - @b Fail
 * - @ref BSP_ERROR_NO_INIT - 串口没有初始化
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_TIMEOUT - 接收超时
 */
int32_t UartRecv( UartId_t uartId, uint8_t *buffer, uint16_t size, uint32_t blockTime )
{
    if ( UartObj[uartId].IsInitialized == false )
        return BSP_ERROR_NO_INIT;
    
    if (buffer == NULL)
        return BSP_ERROR_INVALID_PARAM;

#if UART5_IDLE_DISABLE
    if (uartId == UART_5)
        blockTime = 0;  /* 不使用空闲中断，UART5 仅支持查询接收 */
#endif

    if ( (xSemaphoreTake(UartObj[uartId].uartRxSemaphore, blockTime) == pdTRUE) || (blockTime == 0) )
    {
        uint16_t fifo_readLen = size;
        /* 获取FIFO当前长度，如果FIFO空返回 FIFO_ERROR_NOT_FOUND */
        taskENTER_CRITICAL();
        if(FIFO_SUCCESS == app_fifo_read(&UartObj[uartId].FifoRx, NULL, (uint32_t *)&fifo_readLen))
        {
            if( fifo_readLen > size )
                app_fifo_read(&UartObj[uartId].FifoRx, buffer, (uint32_t *)&size);
            else
                app_fifo_read(&UartObj[uartId].FifoRx, buffer, (uint32_t *)&fifo_readLen);
            taskEXIT_CRITICAL();

            return fifo_readLen;
        }   /* fifo为空 */
        taskEXIT_CRITICAL();
    }
    else    /* 超时 */
    {
        return BSP_ERROR_TIMEOUT;
    }

    return 0;   /* fifo为空 */
}


/**
 * @brief 重定向c库函数printf到串口，重定向后可使用printf函数,需要选择use MicroLIB
 */
int fputc(int ch, FILE *f)
{
#if (LOG_USES_UART)
#ifdef STM32F10X
    USART_SendData(DEBUG_USARTx, (uint8_t) ch);
#elif defined GD32F10X
    usart_data_transmit( DEBUG_USARTx, (uint8_t)ch );
#endif
    if (BSP_ERROR_TIMEOUT == UART_WaitOnFlagUntilTimeout( (UartId_t)(LOG_UART-1), USART_FLAG_TC, RESET, 100 ))
        return BSP_ERROR_TIMEOUT;
#endif

    return ch;
}

/**
 * @brief 重定向c库函数scanf到串口，重写向后可使用scanf、getchar等函数
 */
int fgetc(FILE *f)
{
#if (LOG_USES_UART)
#ifdef STM32F10X
    UART_WaitOnFlagUntilTimeout( (UartId_t)(LOG_UART-1), USART_FLAG_RXNE, RESET, 100 );
    return (int)USART_ReceiveData( DEBUG_USARTx );
#elif defined GD32F10X
    UART_WaitOnFlagUntilTimeout( (UartId_t)(LOG_UART-1), USART_FLAG_RBNE, RESET, 100 );
    return (int)usart_data_receive( DEBUG_USARTx );
#endif
#else
    return 0;
#endif
}

/*********** (C) COPYRIGHT 2020 FiberHome *****END OF FILE****/
